﻿// =====================================================================
//
//  This file is part of the Microsoft Dynamics CRM SDK code samples.
//
//  Copyright (C) Microsoft Corporation.  All rights reserved.
//
//  This source code is intended only as a supplement to Microsoft
//  Development Tools and/or on-line documentation.  See these other
//  materials for detailed information regarding Microsoft code samples.
//
//  THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
//  KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
//  IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
//  PARTICULAR PURPOSE.
//
// =====================================================================
#region

using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
using Microsoft.Xrm.Sdk.XmlNamespaces;

#endregion

namespace Microsoft.Xrm.Sdk.Client.Protocols.Policy
{
	public sealed class EndorsingSupportingTokenPolicyImporter : XrmTokenPolicyImporter
	{
		public override XName TokenRootQuery
		{
			get { return PublicNamespaces.SP + @"EndorsingSupportingTokens"; }
		}
	}

	public sealed class SignedSupportingTokenPolicyImporter : XrmTokenPolicyImporter
	{
		public override XName TokenRootQuery
		{
			get { return PublicNamespaces.SP + @"SignedSupportingTokens"; }
		}
	}

	public abstract class XrmTokenPolicyImporter : ServicePolicyImporter, IPolicyImporter
	{
		public abstract XName TokenRootQuery { get; }

		#region IPolicyImporter Members

		public Boolean CanImport(XDocument document)
		{
			if (!Imported)
			{
				IEnumerable<XElement> bindingElements = from el in document.Descendants(TokenRootQuery)
														select el;
				return bindingElements.Count() > 0;
			}
			return false;
		}

		public ServicePolicy ImportPolicy(XDocument document)
		{
			IEnumerable<XElement> bindingElements = from el in document.Descendants(TokenRootQuery)
													select el;
			foreach (XElement bindingElement in bindingElements)
			{
				IEnumerable<XElement> policies = from el in bindingElement.Descendants(PublicNamespaces.WSP + "Policy")
												 select el;
				foreach (XElement policy in policies)
				{
					IEnumerable<XElement> issuedTokens =
						from el in policy.Descendants(PublicNamespaces.SP + "IssuedToken")
						select el;
					foreach (XElement issuedToken in issuedTokens)
					{
						IEnumerable<XElement> issuers =
							from el in issuedToken.Descendants(PublicNamespaces.SP + "Issuer")
							select el;
						foreach (XElement issuer in issuers)
						{
							IEnumerable<XElement> metadataElements =
								from el in issuer.Descendants(PublicNamespaces.WSA05 + "Metadata")
								select el;

							foreach (XElement metadataElement in metadataElements)
							{
								IEnumerable<XElement> wsxMetadataElements =
									from el in metadataElement.Descendants(PublicNamespaces.WSX + "Metadata")
									select el;

								foreach (XElement wsxMetadataElement in wsxMetadataElements)
								{
									IEnumerable<XElement> metadataSections =
										from el in
											wsxMetadataElement.Descendants(PublicNamespaces.WSX + "MetadataSection")
										select el;

									foreach (XElement metadataSection in metadataSections)
									{
										IEnumerable<XElement> metadataReferences =
											from el in
												metadataSection.Descendants(PublicNamespaces.WSX +
																			"MetadataReference")
											select el;

										foreach (XElement metadataReference in metadataReferences)
										{
											SecureTokenServicePolicy tokenPolicy = new SecureTokenServicePolicy();
											Imported = ExtractValue(tokenPolicy, metadataReference,
																	"SecureTokenServiceTrustEndpoint",
																	PublicNamespaces.WSA05 + "Address");
											return tokenPolicy;
										}
									}
								}
							}

							XElement address = issuer.Element(PublicNamespaces.WSA05 + "Address");
							if (address != null)
							{
								//There is no metadata, i.e. LiveID								
								if (address.Value != WSAddressingConstants.AnonymousUri)
								{
									SecureTokenServicePolicy tokenPolicy = new SecureTokenServicePolicy();
									SetValue(tokenPolicy, "SecureTokenServiceTrustEndpoint", address.Value);
									return tokenPolicy;
								}
							}
						}
					}
				}
			}

			return null;
		}

		#endregion
	}

	public sealed class SecureTokenServicePolicy : ServicePolicy
	{
	}

	internal static class WSAddressingConstants
	{
		internal static string AnonymousUri = "http://www.w3.org/2005/08/addressing/anonymous";
	}
}
